<template>
  <div class="preview-gis-map-component">
    <div :id="idName" ref="mapBox" class="map-class"></div>
    <div v-show="mapLoading" class="layer-loading">
      <a-spin size="large" :delay="500" tip="Loading..."></a-spin>
    </div>
    <!-- 搜索 -->
    <k-gis-search
      class="search-box"
      :visible="currentToolBarAction === 'gisSearchVisible'"
      @fit-bounds="mapBoxFitBoundsMixin"
      @search-entity="searchEntity"
      @open-entity="saveAndOpenEntity"
      @close-search="closeSearch"
    />
    <!-- 筛选器 -->

    <!-- entity detail -->
    <!-- 循环生成，若没有位置信息，根据前者叠加向左偏移 -->
    <div v-if="entityList.length > 0">
      <k-entity-panel
        v-for="entity in entityList"
        :key="entity.id"
        :ref="`entity-${entity.id}`"
        :source-data="entity"
        :relation="relation"
        @open-entity="openOtherEntity"
        @reset-entity="() => {}"
        @show-fixed="showFixedLineLayer"
        @hide-fixed="removeFixedLineLayer"
        @close-entity="closeEntityPanel"
      />
    </div>
    <!-- text panel -->
    <template v-if="textList.length > 0">
      <common-text-editor
        v-for="textItem in textList"
        :id="`box-item-${textItem.i}`"
        :key="textItem.i"
        :text-item="textItem"
        :read-only="true"
      >
      </common-text-editor>
    </template>

    <!-- toolbar -->
    <div class="toolbar" :class="{ 'guest-mode': isLock }">
      <div v-for="(tip, index) in functionList" :key="index">
        <a-tooltip placement="top">
          <template slot="title">
            <span>{{ tip.tooltip }}</span>
          </template>
          <div
            class="btn function-btn-spacing"
            :class="{
              'btn-disabled': tip.disabled,
              'btn-select': currentToolBarAction === tip.click,
            }"
            @click="clickFunction(tip)"
          >
            <a-icon-font class="tool-icon" :type="tip.icon" />
          </div>
        </a-tooltip>
      </div>
      <filter-items
        ref="filter-items"
        :disabled="isLock"
        :filter-content-visible="filterContentVisible"
        :checked-class-keys="checkedClassKeys"
        :checked-relation-keys="checkedRelationKeys"
        :graph-data="rawData"
        @on-check-filter-class="onCheckFilterClass"
        @on-check-filter-relation="onCheckFilterRelation"
        @on-filter-items="onFilterItems"
        @open-filter-content="openFilterContent"
        @close-filter-content="closeFilterContent"
      ></filter-items>
    </div>
  </div>
</template>

<script lang="ts">
/**
 * gis 地图画布
 */
import { Component, Watch, Mixins, Prop } from 'vue-property-decorator'
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
import GisZoomControl from '@/components/gis/gis-analysis/GisZoomControl.vue'
import { getMapTilesByMapTypeAndStyle } from '@/components/knowledge-gis/map-packages/map-tiles'
import KGraphStore from '@/store/modules/k-graph'
// import DataViewStore from '@/store/modules/dataview'
import KGisSearch from '@/components/knowledge-gis/KGisSearch.vue'
import KEntityPanel from '@/components/knowledge-gis/KEntityPanel.vue'
import {
  globalHoverSetFeatureState,
  hoverSetFeatureState,
  selectedSetFeatureState,
  clearSelectedFeatureState,
} from '@/components/gis/map-package/map-utils/highlight-util'
import KnowledgeGisMapMixin from '@/components/knowledge-gis/knowledge-gis-map-mixin'
import './map-style.less'
import { GisInfo } from '@/interface/k-graph-interface'
import CommonTextEditor from '@/components/common/CommonTextEditor/CommonTextEditor.vue'
import FilterItems from '@/components/knowledge-vis/FilterItems.vue'
import { queryKnowledgeGraph } from '@/api/knowledge-graph'
import { cloneDeep } from 'lodash'
import { key } from '@/components/gis/map-package/map-config'
import { shapePrefixInfo, removePrefix } from '@/util/prefix-utils'

@Component({
  components: {
    GisZoomControl,
    KGisSearch,
    KEntityPanel,
    CommonTextEditor,
    FilterItems,
  },
})
export default class PreviewKGisMap extends Mixins(KnowledgeGisMapMixin) {
  @Prop({ type: String, default: 'map' }) idName!: string
  // 返回地图当前的缩放级别
  public get getZoom() {
    return this.mapBox ? this.mapBox.getZoom() : 0
  }
  public projectId: number | null = null // 项目 id
  public currentToolBarAction: string = '' //  当前选中的toolbar 功能

  // 项目锁定
  public get isLock() {
    // return DataViewStore.getLock
    return false
  }

  public get publishNo() {
    return KGraphStore.publishNo || undefined
  }

  public get entityList() {
    return KGraphStore.entityPanelList || []
  }

  public get knowledgeGraphMode(): string {
    return KGraphStore.knowledgeGraphMode
  }

  get isNotAllowed() {
    return this.isPreview || this.isPublish
  }

  get isPreview() {
    return this.knowledgeGraphMode === 'preview'
  }

  get isPublish() {
    return this.knowledgeGraphMode === 'publish'
  }

  //  text start
  public get textList() {
    return KGraphStore.textList || []
  }

  // 关系数据进行细分
  public get relation() {
    return KGraphStore.filterRawData.filterItems.relation || {}
  }

  public get baseUri() {
    return KGraphStore.baseUri
  }

  // 实体图层 id 即点id
  public get entityLayerId(): any {
    // return KGraphStore.gisInfo?.entityLayerId[0]
    return 'Point'
  }
  // 面的id
  public get entityLayerIdFill(): any {
    return 'MultiPolygon'
  }

  public get nameSet() {
    return KGraphStore.sysSetting.nameSet
  }

  public get clickFeatureInfo() {
    return KGraphStore.clickLayerFeatureInfo
  }

  public clickInfo: any = null //  记录点击的实体信息，主要是id

  public functionList: any[] = [
    // {
    //   tooltip: '筛选',
    //   click: 'gisFilter',
    //   icon: 'iconshaixuan',
    //   disabled: false,
    // },
    {
      tooltip: '复位',
      click: 'gisRestoration',
      icon: 'iconhuidaohuabanbeifen3',
      disabled: true,
    },
    {
      tooltip: '搜索',
      click: 'gisSearchVisible',
      icon: 'iconsousuo',
      disabled: false,
    },
  ]

  // 多个功能 统一点击入口
  public clickFunction(action: any) {
    const { click } = action

    if (click === 'gisRestoration') {
      this.resetMap()
      this.currentToolBarAction = ''
    } else {
      this.currentToolBarAction = 'gisSearchVisible'
      this.closeFilterContent() //  close filter window by default
    }
  }

  //  filter start
  public filterContentVisible = false

  public get graphId() {
    return KGraphStore.graphId
  }

  public get searchInput() {
    return KGraphStore.searchInput
  }

  public get checkedClassKeys() {
    return KGraphStore.checkedClassKeys
  }

  public get checkedRelationKeys() {
    return KGraphStore.checkedRelationKeys
  }

  public get rawData() {
    return KGraphStore.filterRawData
  }

  @Watch('rawData', { immediate: true, deep: true })
  public handleRawData(newValue: any) {
    if (newValue?.filterItems?.class) {
      this.$nextTick(() => {
        const filterItems = this.$refs['filter-items'] as FilterItems
        filterItems.initFilterItems()
      })
    }
  }

  public onCheckFilterClass(checkedKeys: any) {
    KGraphStore.setClassKeys(checkedKeys)
  }

  public onCheckFilterRelation(checkedKeys: any) {
    KGraphStore.setRelationKeys(checkedKeys)
  }

  public async onFilterItems() {
    const formData = new FormData()
    formData.append('projectId', this.projectId?.toString() || '')
    const withClass = JSON.stringify(
      this.checkedClassKeys.map((item: any) => {
        return `${KGraphStore.baseUri}#${item}`
      })
    )
    const hasRelation = JSON.stringify(
      this.checkedRelationKeys.map((item: any) => {
        return `${KGraphStore.baseUri}#${item}`
      })
    )
    formData.append('withClass', withClass)
    formData.append('hasRelation', hasRelation)
    const response = await queryKnowledgeGraph({
      data: formData,
    })
    const { code, data } = response.data
    const shapeData = shapePrefixInfo(data, this.baseUri)
    if (code === 200) {
      this.closeFilterContent()
      if (this.checkedRelationKeys.length === 0) {
        shapeData.edges = []
      }
      this.updateDashboard()

      KGraphStore.setReloadGraph(shapeData)
      //  在发布态的时候，暂存dynamicFilters
      if (this.isPublish) {
        KGraphStore.setDynamicFilters(shapeData.dynamicFilters)
      }
    }
  }

  public openFilterContent() {
    // if (this.isLoadGraphData) {
    this.filterContentVisible = true
    //  close other func box
    this.currentToolBarAction = ''
    // }
  }

  public closeFilterContent() {
    this.filterContentVisible = false
  }

  public updateDashboard() {
    this.updateMap()
    KGraphStore.setEntityPanelList([])
  }

  public get dynamicFilters() {
    return KGraphStore?.dynamicFilters ?? undefined
  }

  /**
   * 查询项目信息
   */
  public async queryDashboardData() {
    const response: any = await KGraphStore.queryKGDashBoard({
      knowledgeGraphFileId: KGraphStore.graphId,
    })
    if (response.data.code === 200) {
      await this.updateMap()
    } else {
      this.$message.error('错误')
    }
  }

  @Watch('clickFeatureInfo', { deep: true })
  public handleClickedFeatrueInfo(newValue: Array<any>) {
    if (newValue === null) {
      return
    }
    //  非预览态监听点击事件
    if (
      newValue.length > 0 &&
      ['circle', 'fill'].includes(newValue[0].layer.type)
    ) {
      //  排除点击线数据
      if (
        this.clickInfo === null ||
        (this.clickInfo && this.clickInfo.id !== newValue[0].id)
      ) {
        //  save opened entity before empty
        // this.saveOpenEntityInfo()
        //  empty store save
        // KGraphStore.setEntityPanelList([])
        // KGraphStore.setGridList([])
        this.saveOpenEntityInfo()

        this.clickInfo = {
          id: newValue[0].id,
        }

        const objectName = `${this.baseUri}#${newValue[0].id}`
        // const target = newValue[0]
        KGraphStore.queryEntityInfo({
          objectName: window.btoa(encodeURIComponent(objectName)),
          knowledgeGraphFileId: KGraphStore.graphId,
        })
      }
    }
  }

  //  关闭并保存打开的实体面板
  public saveOpenEntityInfo() {
    if (this.entityList.length > 0) {
      const target = cloneDeep(this.entityList)
      // eslint-disable-next-line no-restricted-syntax
      for (const entity of target) {
        const instance: any = this.$refs[`entity-${entity.id}`] as Vue
        instance[0].closeEntity()
      }
    }
  }

  public closeEntityPanel(dataInfo: any) {
    const { entityData } = dataInfo
    this.clickInfo = null

    KGraphStore.removeEntityPanelList(entityData)

    //  delete gridList
    KGraphStore.removeGridList(entityData.id)

    //  重置点击实体的存储
    // KGraphStore.setClickLayerFeatureInfo(null)
  }

  public saveAndOpenEntity(dataInfo: any) {
    KGraphStore.setEntityPanelList([])
    KGraphStore.setGridList([])
    this.openOtherEntity(dataInfo)
  }

  /**
   * 是否该实体 已经有实体面板
   * @param entityName 实体名称
   */
  public checkIfEntityExist(entityName: string) {
    // eslint-disable-next-line no-restricted-syntax
    for (const item of this.entityList) {
      if (item.name === entityName) {
        return true
      }
    }
    return false
  }

  public async openOtherEntity(dataInfo: any) {
    const { id, searchKey } = dataInfo
    // 若实体面板已经打开，则不再重复打开
    if (this.checkIfEntityExist(searchKey)) {
      return
    }
    const objectName = `${this.baseUri}#${id}`
    // const target = newValue[0]
    const response = await KGraphStore.queryEntityInfo({
      objectName: window.btoa(encodeURIComponent(objectName)),
      knowledgeGraphFileId: KGraphStore.graphId,
    })
    const { data } = response.data
    const shapeData = shapePrefixInfo(data, this.baseUri)

    const geoInfo: any = {}
    // eslint-disable-next-line no-restricted-syntax
    shapeData.items.forEach((item: any) => {
      item.children.forEach((child: any) => {
        if (['纬度', '经度'].includes(child.attrName)) {
          const attributeName = removePrefix(child.attrName, this.baseUri)
          geoInfo[attributeName] = child.attrValue
        }
      })
    })
    if ('纬度' in geoInfo) {
      KGraphStore.setSelectedEntityNode({
        id: String(id),
        attrs: geoInfo,
      })
    } else if (searchKey && searchKey.length > 0) {
      //  for 面数据 focus
      const polygonId: any = this.entityLayerIdFill
      const entityData = KGraphStore.layerList.find((layer: any) => {
        return layer.id === polygonId
      })
      const entityDataFeatures = entityData?.geojson.features
      const searchResult = entityDataFeatures.filter((item: any) => {
        const reg = new RegExp(searchKey, 'gi')
        const { label } = item.properties
        if (label) {
          return label.match(reg)
        }
        return false
      })
      if (searchResult.length > 0) {
        const searchResultFirstGeometryCoordinates: any =
          searchResult[0].geometry.coordinates[0][0][0]
        this.mapBox.easeTo({
          center: searchResultFirstGeometryCoordinates,
          zoom: 14,
          duration: 1000,
        })
        this.focusEntityByLngLatAndId(searchResult[0].id)
      } else {
        //  for binjiangqu case
        this.searchGis(searchKey)
      }
    }
  }

  public async searchGis(name: string) {
    const parameters: any = {
      postStr: {
        searchWord: name,
        searchType: '1',
        needSubInfo: false,
        needAll: false,
        needPolygon: true,
        needPre: true,
      },
      tk: key,
    }
    const response: any = await KGraphStore.searchAdministrative(parameters)
    if (response.data.returncode === '100') {
      const { bound } = response.data.data[0]
      if (bound) {
        const [lat1, lnt1, lat2, lnt2] = bound.split(',')
        const boundArray: any[] = [
          [lat1, lnt1],
          [lat2, lnt2],
        ]

        this.mapBoxFitBoundsMixin(boundArray)
        // this.$emit('fit-bounds', boundArray)
      }
    }
  }

  public get selectedEntityNode() {
    return KGraphStore.selectedEntityNode
  }

  /**
   * 左侧知识图谱选择实体
   * @param entityNode
   */
  @Watch('selectedEntityNode', { deep: true })
  public selectedEntityNodeChange(entityNode: any) {
    // 聚焦实体，
    const { attrs } = entityNode
    this.mapBox.easeTo({
      center: [attrs['经度'], attrs['纬度']],
      zoom: 14,
      duration: 1000,
    })
    this.focusEntityByLngLatAndId(entityNode.id)
  }

  // 暂时使用
  public currentMapTypeStyle: any = {
    mapType: 1,
    tileStyle: 1,
  }
  // map 全局 loading
  public get mapLoading(): boolean {
    return KGraphStore.mapLoading
  }
  // 所有图层
  public get layerList() {
    return KGraphStore.layerList
  }
  // dashboard gis info
  public get gisInfo(): GisInfo | null {
    return KGraphStore.gisInfo
  }
  public get gisInfoMapTypeStyle(): { mapType: number; tileStyle: number } {
    return {
      mapType: this.gisInfo?.mapType || 1,
      tileStyle: this.gisInfo?.tileStyle || 1,
    }
  }
  // 可见图层（带有排列顺序）
  public get layerIndexOrderOfVisible() {
    return KGraphStore.layerList
      .filter((item: any) => item.visible === 1)
      .sort((layer1: any, layer2: any) => layer1.order - layer2.order)
  }

  // public get mode() {
  //   return KGraphStore.mode
  // }

  public async mounted() {
    this.projectId = KGraphStore.projectId || Number(this.$route.params.id)
    KGraphStore.setEntityPanelList([])
    await this.updateMap()
  }

  /**
   * 更换地图样式
   * @param mapType 地图类型 1 - 高德
   * @param tileStyle 底图样式
   * @private
   */
  private changeMapTypeStyle(mapType: number = 1, tileStyle: number = 1) {
    this.mapBox.setStyle(getMapTilesByMapTypeAndStyle(mapType, tileStyle)) // 修改地图样式
    KGraphStore.setDashboardGisInfo({ key: 'tileStyle', value: tileStyle })
    KGraphStore.setDashboardGisInfo({ key: 'mapType', value: mapType })
    this.currentMapTypeStyle.mapType = mapType
    this.currentMapTypeStyle.tileStyle = tileStyle
  }

  /**
   * 更新地图
   */
  public async updateMap() {
    if (this.mapBox) {
      this.clearLayer() // 清除图层
      const { currentMapTypeStyle } = this
      // 配置 是否需要更换底图
      if (
        currentMapTypeStyle &&
        currentMapTypeStyle.tileStyle !== this.gisInfo?.tileStyle
      ) {
        this.changeMapTypeStyle(this.gisInfo?.mapType, this.gisInfo?.tileStyle)
        this.$nextTick(() => {
          this.initAddLayerOfVisible()
        })
      } else {
        this.initAddLayerOfVisible()
      }
    } else {
      this.$nextTick(() => {
        this.initMap()
        this.mapResizeMixin()
      })
    }
  }

  /**
   * 清空图层， 重新画新的图层
   */
  public clearLayer() {
    if (this.mapBox) {
      KGraphStore.layerList.forEach((layer: any) => {
        const checkLayerLabelIsExist: boolean = !!this.mapBox.getLayer(
          `label-${layer.id}`
        )
        if (checkLayerLabelIsExist) {
          this.mapBox.removeLayer(`label-${layer.id}`)
        }

        const checkLayerArrowIsExist: boolean = !!this.mapBox.getLayer(
          `arrow-${layer.id}`
        )
        if (checkLayerArrowIsExist) {
          this.deleteLayerArrowByIds(layer.id)
        }

        const checkLayerIsExist: boolean = !!this.mapBox.getLayer(`${layer.id}`)
        if (checkLayerIsExist) {
          this.mapBox.removeLayer(`${layer.id}`)
          this.mapBox.removeSource(`source-${layer.id}`)
        }
      })
    }
  }

  /**
   * 地图复位
   */
  private resetMap() {
    this.resetMapMixin(this.layerList, KGraphStore.layerData)
  }

  /**
   * 实例化地图
   */
  public async initMap() {
    KGraphStore.setMapLoading(true)
    this.initMapBoxMixin(
      this.gisInfo?.mapType,
      this.gisInfo?.tileStyle,
      this.idName
    ) // 实例化 mapbox gl
    this.mapBox.on('load', () => {
      this.initAddLayerOfVisible() // 初始化 加载可视状态的图层
      this.initAndUpdateMapboxEvent() // 地图事件  当删除一些图层时需要更新
    })
    // KGraphStore.setNonEditMapboxInstance(this.mapBox) //  store 存储 mapbox 实例
    this.addOrRemoveScaleControlMixin(true)
    this.addCoordinatesControlMixin()
    // this.addNavigationControlMixin(this.resetMap)
  }

  /**
   * 初始化/更新 地图事件
   */
  public initAndUpdateMapboxEvent() {
    this.initAndUpdateMapboxOnClickEvent()
    this.initAndUpdateMapboxOnMouseEvent()
  }

  public initAndUpdateMapboxOnMouseEvent() {
    this.mapBox.off('mousemove', ($event: any) => this.globalMouseEvent($event))
    this.mapBox.on('mousemove', ($event: any) => this.globalMouseEvent($event))
  }

  /**
   * 地图点击事件的初始化与更新
   */
  public initAndUpdateMapboxOnClickEvent() {
    this.mapBox.off('click', ($event: any) => this.mapboxClickEvent($event))
    this.mapBox.on('click', ($event: any) => this.mapboxClickEvent($event))
  }

  /**
   * 地图点击事件
   * @param $event
   */
  public mapboxClickEvent($event: any) {
    const features = this.mapBox.queryRenderedFeatures($event.point, {
      layers: this.exitLayerIds(),
    })
    if (features.length > 0) {
      KGraphStore.setClickLayerFeatureInfo(features)
      // 高亮点击的要素
      const { id, layer } = features[0]
      const layerId: string = layer.id
      clearSelectedFeatureState(this.mapBox)
      selectedSetFeatureState(this.mapBox, layerId, [id])
    }
    // else if (this.currentToolBarAction !== 'gisSetting') {
    //   KGraphStore.setCurrentToolBarAction('gisSetting')
    //   clearSelectedFeatureState(this.mapBox) // 清除选中的要素
    // } else if (this.currentToolBarAction === 'gisSetting') {
    //   KGraphStore.setCurrentToolBarAction(null)
    //   clearSelectedFeatureState(this.mapBox) // 清除选中的要素
    // }
  }

  /**
   * 全局鼠标事件
   * TODO 需要修改
   */
  public globalMouseEvent($event: any) {
    const features = this.mapBox.queryRenderedFeatures($event.point, {
      layers: this.exitLayerIds(),
    })
    if (features.length > 0) {
      const featureFirst = features[0]
      // const layerId = featureFirst.layer.id
      // TODO hover 高亮
      globalHoverSetFeatureState(this.mapBox, featureFirst, 'mousemove')
      $event.preventDefault()
      this.mapBox.getCanvas().style.cursor = 'pointer'
      const coordinates = featureFirst.geometry.coordinates.slice()
      const currentFeatureProperty: any = featureFirst.properties
      //  remove useless property
      const propertyInShow = Object.fromEntries(
        Object.entries(currentFeatureProperty).filter(
          ([propertyKey]) =>
            !['color', '纬度', '经度', 'id', 'name', '简称'].includes(
              propertyKey
            )
        )
      )
      // delete currentFeatureProperty._record_id_
      const propertyKey: any[] = Object.keys(propertyInShow)
      if (propertyKey.length > 0) {
        let attributesDom = ''
        propertyKey.forEach((item: any) => {
          attributesDom += `<div class="attr-key-value">${item}: ${currentFeatureProperty[item]}</div>`
        })
        while (Math.abs($event.lngLat.lng - coordinates[0]) > 180) {
          coordinates[0] += $event.lngLat.lng > coordinates[0] ? 360 : -360
        }
        this.mapboxPopup
          .setLngLat($event.lngLat)
          .setHTML(`<div>${attributesDom}</div>`)
          .setMaxWidth('300px')
          .addTo(this.mapBox)
      }
    }
  }

  /**
   * 地图图层添加鼠标事件 (高亮， tooltip)
   */
  public addMouseEventToMapBoxByLayerId(layerId: string) {
    this.mapBox.on('mouseleave', layerId, ($event: any) => {
      this.mapBox.getCanvas().style.cursor = ''
      this.mapboxPopup.remove()
      hoverSetFeatureState(this.mapBox, $event, layerId, 'mouseleave')
    })
  }

  /**
   * 短暂显示常驻图层
   * @param layerId 图层 id
   * @param fixed
   */
  public showFixedLineLayer(layerId: string) {
    const currentFixedLayer: any = KGraphStore.allLayerList.find(
      (layer: any) => layer.id === layerId
    )
    if (currentFixedLayer) {
      const { id, type, arrow } = currentFixedLayer
      this.checkLayerDataExitAndAddLayer(id, type, arrow, true)
    }
  }

  /**
   * 删除短暂显示的常驻图层
   * @param fixedId
   */
  public removeFixedLineLayer(fixedId: string) {
    this.deleteLayerArrowByIds(fixedId)
    this.deleteLayerByIds([fixedId])
  }

  /**
   * 更新图层层级关系
   * visibleLayers 已显示的图层
   * includeLayerId 需要额外增加的图层
   */
  public updateMapLayerOrder(visibleLayers: any, includeLayerId?: string) {
    let needSortLayer: any[] = visibleLayers
    if (includeLayerId) {
      needSortLayer = KGraphStore.layerList.filter(
        (item: any) => item.visible === 1 || item.id === includeLayerId
      )
    }
    this.$nextTick(() => {
      for (let i: number = 0; i <= needSortLayer.length - 2; i += 1) {
        const layerId1: string = `${needSortLayer[i].id}`
        const layerId2: string = `${needSortLayer[i + 1].id}`
        const layer1: any = this.mapBox.getLayer(layerId1)
        const layer2: any = this.mapBox.getLayer(layerId2)
        // 各图层对 label 的位置排序
        const layer1LabelId: string = `label-${layerId1}`
        const layer1Label: any = this.mapBox.getLayer(layer1LabelId)
        if (layer1Label) {
          this.mapBox.moveLayer(layerId1, layer1LabelId)
        }

        if (layer1 && layer2) {
          // beforeId 要在之前插入新图层的现有图层id。查看地图时， 图层将出现在图层下方 。如果省略，则图层将附加到图层数组的末尾并出现在地图上的所有其他图层之上。
          this.mapBox.moveLayer(layerId2, layerId1)
        }
      }
      // this.addMouseEventToMapBoxByLayerId(`${needSortLayer[0].id}`)
    })
  }

  /**
   * 检查已有 图层 是否是显示状态 添加图层
   */
  public initAddLayerOfVisible() {
    this.initAddEmptyMixin()
    // 可视状态图层
    const visibleLayers: any[] = this.layerList.filter(
      (layer: any) => layer.visible === 1
    )
    if (visibleLayers.length > 0) {
      this.renderLayerAfterGetLayerData(visibleLayers)
      this.updateMapLayerOrder(this.layerIndexOrderOfVisible) // 调整图层层级
    }
    KGraphStore.setMapLoading(false)
  }

  /**
   * 渲染指定多个图层（先获取数据）
   * @param layers
   */
  public async renderLayerAfterGetLayerData(layers: any[]) {
    if (layers.length > 0) {
      KGraphStore.setMapLoading(true)
      // await this.getLayerDataByLayers(layers) // 获取所有可视图层的 渲染数据
      layers.forEach((layer: any) => {
        // 根据id去图层数据里面找相关的地图信息
        const targetLayer = cloneDeep(layer)
        targetLayer.geojson.features = layer.geojson.features.filter(
          (feature: any) => {
            return KGraphStore.checkedClassKeys.includes(
              feature.properties.class
            )
          }
        )
        KGraphStore.addLayerData({ [targetLayer.id]: targetLayer })
      })
      this.renderVisibleLayer(layers) // 渲染各可视状态图层
      this.resetMap() // 基于图层包围盒复位
      KGraphStore.setMapLoading(false)
    }
  }

  /**
   * 获取多个图层的渲染数据
   */
  public async getLayerDataByLayers(layers: any[]) {
    // 图层数据不存在的图层， 避免重复获取图层数据
    // const dataNonExistentLayer: any[] = layers.filter((layer: any) => {
    //   return !KGraphStore.layerData[layer.id]
    // })
    if (layers.length > 0) {
      const requests = layers.map(async (layer: any) => {
        return this.queryLayerDataByLayerId(layer.id)
      })
      await Promise.allSettled(requests)
    }
  }

  /**
   * 获取图层数据
   * @param layerId
   * @param fixedLayer 是否绘制常驻图层
   */
  public async queryLayerDataByLayerId(
    layerId: number,
    fixedLayer: boolean = false
  ) {
    const parameters: any = {
      projectId: this.projectId,
      layerId,
      kGraph: !fixedLayer || true, //  无论是否fixedLayer，都是true
      publish: this.isPublish ? true : undefined,
      dynamicFilters: this.dynamicFilters,
      publishNo: this.publishNo,
    }
    const response: any = await KGraphStore.queryLayerDataById(parameters)
    return response
  }

  /**
   * 渲染所有有数据的图层
   * @private
   */
  private renderVisibleLayer(visibleLayers: any[]) {
    visibleLayers.forEach((layer: any) => {
      const beforeId: string = this.getLayerBeforeId(layer.id) // 获取图层 beforeId
      this.addLayerToMap(layer.id, layer.type, beforeId, layer.arrow)
    })
  }

  /**
   * 获取 定位图层位置 beforeId， 用于添加图层是定位
   * @private
   */
  private getLayerBeforeId(layerId: number) {
    const visibleLayers: any[] = this.layerList.filter(
      (layer: any) => layer.visible === 1
    )
    const index: number = visibleLayers.findIndex(
      (layer: any) => layer.id === layerId
    )
    let beforeId: string | null = 'base-empty-layer'
    if (index > 0 && visibleLayers[index - 1].id) {
      const layerIdString: string = String(visibleLayers[index - 1].id)
      const beforeIdExist: boolean = !!this.mapBox.getLayer(layerIdString)
      beforeId = beforeIdExist ? layerIdString : 'base-empty-layer'
    }
    return beforeId
  }

  /**
   * 存在的图层
   */
  public exitLayerIds() {
    const exitLayerIds: string[] = []
    if (this.mapBox) {
      KGraphStore.layerList.forEach((layer: any) => {
        const mapLayer = this.mapBox.getLayer(String(layer.id))
        if (mapLayer) {
          exitLayerIds.push(String(layer.id))
        }
      })
    }
    return exitLayerIds
  }

  /**
   * 添加图层之前的获取图层数据， 并添加图层
   * @param layerId 图层id
   * @param layerType 图层类型
   * @param arrow  是否有箭头
   * @param fixedLayer 是否绘制常驻图层
   */
  public async checkLayerDataExitAndAddLayer(
    layerId: number,
    layerType: string,
    arrow: boolean = false,
    fixedLayer: boolean = false
  ) {
    console.log('fixedLayer:', fixedLayer)
    // 定位图层位置
    const beforeId: string = this.getLayerBeforeId(layerId)
    if (KGraphStore.layerData[layerId]) {
      this.addLayerToMap(layerId, layerType, beforeId, arrow)
    }
  }

  /**
   * 添加图层
   * @param layerId 图层id
   * @param layerType 图层类型
   * @param beforeId 图层 beforeId
   * @param arrow 线图层是否带箭头
   */
  public addLayerToMap(
    layerId: any,
    layerType: string,
    beforeId: string,
    arrow: boolean = false
  ) {
    const layerDataInfo: any = KGraphStore.layerData[layerId]
    if (!layerDataInfo) {
      return
    }
    if (layerType === 'circle') {
      this.addPointMixin(layerDataInfo, layerId, beforeId)
    } else if (layerType === 'line') {
      this.addLineMixin(layerDataInfo, layerId, beforeId, arrow)
    } else if (layerType === 'fill') {
      this.addPolygonMixin(layerDataInfo, layerId, beforeId)
    }
    // 是否显示实体名称 label
    // const isEntityLayer: boolean = layerId === this.entityLayerId
    if (this.nameSet !== 'hide') {
      //  TODO 增加第二个参数，用于显示简称
      this.addLabelMixin(layerId, this.nameSet === 'abbr' ? '简称' : 'label')
    }
    this.addMouseEventToMapBoxByLayerId(String(layerId))
  }

  public get currentGridItem() {
    return KGraphStore.currentGridItem?.visible ?? false
  }

  /**
   * 高亮实体
   */
  public focusEntityByLngLatAndId(entityId: any) {
    const entityIds: any[] = entityId ? [entityId] : []
    selectedSetFeatureState(this.mapBox, this.entityLayerId, entityIds)
  }
  /**
   * 搜索实体名称
   */
  public searchEntity(searchKey: string) {
    if (!searchKey) {
      this.$message.warning('请输入搜索关键字')
      this.focusEntityByLngLatAndId(null)
      return
    }
    const entityDataFeatures =
      KGraphStore.layerData[this.entityLayerId].geojson.features
    const searchResult = entityDataFeatures.filter((item: any) => {
      const reg = new RegExp(searchKey, 'gi')
      const { label } = item.properties
      if (label) {
        return label.match(reg)
      }
      return false
    })
    if (searchResult.length > 0) {
      const searchResultFirstGeometryCoordinates: any =
        searchResult[0].geometry.coordinates
      this.mapBox.easeTo({
        center: searchResultFirstGeometryCoordinates,
        zoom: 14,
        duration: 1000,
      })
      this.focusEntityByLngLatAndId(searchResult[0].id)
    } else {
      this.focusEntityByLngLatAndId(null)
      this.$message.warning('没有搜索到相关实体!')
    }
  }

  public closeSearch() {
    this.currentToolBarAction = ''
  }
}
</script>

<style scoped lang="less">
.preview-gis-map-component {
  height: 100%;
  position: relative;

  .map-class {
    height: 100%;
    position: relative;
    width: 100%;
  }

  .layer-loading {
    align-items: center;
    background-color: rgba(87, 96, 230, 0.1);
    display: flex;
    height: 100%;
    justify-content: center;
    left: 0;
    position: absolute;
    top: 0;
    width: 100%;
    z-index: 100;
  }

  .search-box {
    left: 100px;
    position: fixed;
    top: 138px;
  }

  .toolbar {
    background-color: #fff;
    display: flex;
    flex-direction: row-reverse;
    height: 38px;
    left: 100px;
    line-height: 38px;

    position: fixed;
    top: 100px;
    transition: width 0.2s ease;
    vertical-align: middle;

    .tool-icon {
      cursor: pointer;
      font-size: 16px;
      height: 26px;
      margin: 0 2px;
      padding: 4px;
    }

    .btn-select {
      background-color: rgba(105, 115, 255, 0.1);
      color: #6973ff;
    }

    .divider {
      background: #999;
      height: 14px;
      margin: 10px 8px;
      width: 1px;
    }

    /deep/ .ant-kg-appl-btn.ant-kg-appl-btn-link {
      color: #5d637e;

      &:hover .tool-icon {
        background-color: #f1f1f1;
        color: #5561ff !important;
      }
    }
  }

  .guest-mode {
    user-select: none;

    /deep/ .ant-kg-appl-btn {
      cursor: not-allowed;
      opacity: 0.45;
    }
  }
}
</style>
